package lol.clann.minecraft.springboot.plugin.bukkit.config.jackson;

import com.google.auto.service.AutoService;
import com.ruoshui.utils.json.JsonUtils;
import lol.clann.minecraft.springboot.api.bukkit.constant.NBTTypeEnum;
import lol.clann.minecraft.springboot.api.bukkit.utils.NBTUtils;
import lol.clann.minecraft.springboot.api.context.SpringContext;
import lol.clann.minecraft.springboot.api.model.LazyField;
import lol.clann.minecraft.springboot.api.spi.jackson.JacksonSerializer;
import lol.clann.minecraft.springboot.bukkit.utils.NMSClasses;
import relocate.com.fasterxml.jackson.core.JsonGenerator;
import relocate.com.fasterxml.jackson.databind.JsonSerializer;
import relocate.com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;
import java.util.Map;

/**
 *
 * @author pyz
 * @date 2019/5/18 2:56 PM
 */
@AutoService(JacksonSerializer.class)
public class NBTTagCompoundSerializer extends JsonSerializer<Object> implements JacksonSerializer {

    private LazyField<NBTUtils> nbtUtils = LazyField.of(() -> SpringContext.getBean(NBTUtils.class));

    @Override
    public Class getType() {
        return NMSClasses.getNBTTagCompound();
    }

    /**
     * Method that can be called to ask implementation to serialize
     * values of type this serializer handles.
     *  @param value Value to serialize; can <b>not</b> be null.
     * @param gen Generator used to output resulting Json content
     * @param serializers Provider that can be used to get serializers for
     */
    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (value == null) {
            gen.writeNull();
            return;
        }
        Map<String, Object> map = (Map<String, Object>) nbtUtils.get().getValue(value);
        if (map == null) {
            gen.writeNull();
            return;
        }
        gen.writeStartObject();
        for (Map.Entry<String, Object> kv : map.entrySet()) {
            String k = kv.getKey();
            gen.writeFieldName(k);
            Object v = kv.getValue();
            NBTTypeEnum type = NBTTypeEnum.getByType(v.getClass());
            if (NBTTypeEnum.NBTTagCompound == type || NBTTypeEnum.NBTTagList == type) {
                gen.writeObject(v);
            } else if (type.getField().getField().getType().isArray()) {
                gen.writeString(type.getIdentity() + JsonUtils.writeValueAsString(type.getField().get(v)));
            } else {
                gen.writeString(type.getIdentity() + type.getField().get(v));
            }
        }
        gen.writeEndObject();
    }

}
